﻿using System;
using System.Collections.Generic;
using System.IO;
using System.Xml;
using System.Xml.Linq;

using MiP.Common;
using MiP.Xml.Core;
using MiP.XmlCmd.Shell.Variables;
using MiP.XmlCmd.Shell.XmlSource;

namespace MiP.XmlCmd.Shell.Commands
{
    public class TransformCommand : Command
    {
        private readonly IXmlSource _xmlSource;
        private readonly IVariableSourceParser _variableSourceParser;
        private readonly IXTransformator _transformator;
        private readonly ILogger _logger;

        public TransformCommand(IXmlSource xmlSource, IVariableSourceParser variableSourceParser, IXTransformator transformator, ILogger logger)
        {
            if (xmlSource == null)
                throw new ArgumentNullException("xmlSource");
            if (variableSourceParser == null)
                throw new ArgumentNullException("variableSourceParser");
            if (transformator == null)
                throw new ArgumentNullException("transformator");
            if (logger == null)
                throw new ArgumentNullException("logger");

            _xmlSource = xmlSource;
            _variableSourceParser = variableSourceParser;
            _transformator = transformator;
            _logger = logger;
        }

        public override void Execute()
        {
            XElement configFile = _xmlSource.Load(Arguments.SourceFile);

            IDictionary<string, string> variables = _variableSourceParser.Parse(Arguments.VariableSources);

            IEnumerable<XElement> files = GetFiles(Arguments.TransformFiles);

            configFile = _transformator.Transform(configFile, files, variables);

            XmlWriterSettings settings = new XmlWriterSettings
            {
                Indent = true,
                IndentChars = "    ",
                NamespaceHandling = NamespaceHandling.OmitDuplicates,
                NewLineChars = Environment.NewLine
            };

            CreateRequiredDirectory(Arguments.DestinationFile);

            using (XmlWriter writer = XmlWriter.Create(Arguments.DestinationFile, settings))
                configFile.WriteTo(writer);
        }

        private void CreateRequiredDirectory(string destinationFile)
        {
            string directory = Path.GetDirectoryName(Path.GetFullPath(destinationFile));
            if (directory != null && !Directory.Exists(directory))
                Directory.CreateDirectory(directory);
        }

        private IEnumerable<XElement> GetFiles(IEnumerable<string> filenames)
        {
            foreach (string filename in filenames)
            {
                if (!_xmlSource.Exists(filename))
                {
                    _logger.Warn("File does not exist: '{0}'!", filename);
                    continue;
                }

                yield return _xmlSource.Load(filename);
            }
        }
    }
}